///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2009. Dimarik
//
///////////////////////////////////////////////////////////////////////////////

package
{

import com.bit101.components.CheckBox;
import com.bit101.components.ComboBox;
import com.bit101.components.InputText;
import com.bit101.components.Label;
import com.bit101.components.ProgressBar;
import com.bit101.components.PushButton;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.net.FileReference;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.system.System;
import flash.utils.ByteArray;

import ru.goodcore.display.SWFGIFMovieClip;
import ru.goodcore.utils.ActivityListener;
import ru.goodcore.utils.getDefinitionNames;

import flash.utils.getTimer;
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;

/*
import flash.utils.getTimer;
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
*/

/**
 *  @author				Dimarik
 *  @version			1.0
 *  @langversion		3.0
 *  @playerversion		9.0
 * 
 */
[SWF(width="1024", height="768", frameRate="21", backgroundColor="#E0EEEE")]

public class GIFMovieClipTest extends Sprite {

	//-------------------------------------------------------------------------
	//
	//   Constructor
	//
	//-------------------------------------------------------------------------

	public function GIFMovieClipTest() {
		super();
		this.init();
	}

	//-------------------------------------------------------------------------
	//
	//   Private variables
	//
	//-------------------------------------------------------------------------

	/**
	 * @private 
	 */
	private var _qname:			QName;

	/**
	 * @private 
	 */
	private var _mc:			MovieClip;

	/**
	 * @private 
	 */
	private var _comboBox:		ComboBox;
	private var _comboBoxIndex:	uint;

	/**
	 * @private 
	 */
	private var _checkBox:		CheckBox;

	/**
	 * @private 
	 */
	private var _inputText:		InputText;

	/**
	 * @private 
	 */
	private var _progressBar:	ProgressBar;

	/**
	 * @private 
	 */
	private var _label:			Label;

	/**
	 * @private 
	 */
	private var _labelSize:		Label;

	/**
	 * @private 
	 */
	private var _useDelays:		Boolean = true;

	/**
	 * @private 
	 */
	private var _start:			Number;

	/**
	 * @private 
	 */
	private var _data:			ByteArray;

	//-------------------------------------------------------------------------
	//
	//   Private methods
	//
	//-------------------------------------------------------------------------

	public function init():void {

/*
		var superClass:		Class;
		var testClass:		Class;
		superClass = DisplayObject;
		testClass = Sprite;
		testClass = URLLoader;
		var className:String = getQualifiedClassName(superClass);
		trace( testClass, 'наследует', superClass, '?', describeType(testClass)..extendsClass.(@type == className).length() == 1 );
		trace( testClass, 'наследует', superClass, '?', superClass.prototype.isPrototypeOf( testClass.prototype ) );
*/

		super.stage.scaleMode = StageScaleMode.NO_SCALE;
		super.stage.align = StageAlign.TOP_LEFT;
		
		var activityListener:ActivityListener = new ActivityListener();
		activityListener.x = super.stage.stageWidth - activityListener.width - 20;
		activityListener.y = 5;
		super.stage.addChild(activityListener);

		super.stage.addEventListener(Event.RESIZE, this.handler_resize);

		var uris:Array = [
			'http://www.ainmarh.com/women.gif',
			'http://c0658142.cdn.cloudfiles.rackspacecloud.com/fdcbeffab56556536cc760f76661d675d6555ada_96s.jpg',
			'http://vseikonki.ucoz.ru/002/Rossiya-Russia.png',
			'http://www.pixeljoint.com/files/icons/full/food.gif',
			'http://img2.pict.com/d8/f3/2c/3555269/0/lost.gif',
			'http://gifzona.com/i/mult/05.gif',
			'http://gifzona.com/i/priroda/1111.gif',
			'http://livegif.ru/Gallery/BEST/fox1.gif',
			'http://pimg.dt00.net/pnews/flashki.ru/681770_b.gif',
			'http://www.gas13.ru/v3/pixelart/wall.gif',
			'http://www.gas13.ru/v3/tutorials/11-5.gif',
			'http://www.gas13.ru/v3/tutorials/8-16.gif',
			'http://www.gifandgif.eu/animated_gif/Arrows/Animated%20Gif%20Arrows%20(104).gif',
			'http://www.livegif.ru/Gallery/ZVERI/BIRDS/BIRDHUML.gif',
			'http://www.pixeljoint.com/files/icons/fool.gif',
			'http://www.pixeljoint.com/files/icons/full/4.gif',
			'http://www.pixeljoint.com/files/icons/full/assault_prototype.gif',
			'http://www.pixeljoint.com/files/icons/full/avat.gif',
			'http://www.pixeljoint.com/files/icons/full/dog.gif',
			'http://www.pixeljoint.com/files/icons/full/newmario.gif',
			'http://www.pixeljoint.com/files/icons/full/pcdesign_final.gif',
			'http://www.pixeljoint.com/files/icons/full/shoe.gif',
			'http://www.pixeljoint.com/files/icons/honey_run_arm00.gif',
			'http://www.pixeljoint.com/files/icons/px_spear.gif',
			'http://gifdr.narod.ru/i/dr/03.gif',
			'http://gifdr.narod.ru/i/dr/10.gif',
			'http://www.princeton.edu/~rvdb/JAVA/election2004/TwoMaps.gif',
			'http://www.solarviews.com/raw/jup/ganymed3.gif',
			'http://www.pixeljoint.com/files/icons/full/completed.gif'
		];

		this._checkBox = new CheckBox(super.stage, 500, 35, 'use gif delays', this.handler_delayChange);
		this._checkBox.selected = true;

		this._label = new Label(super.stage, 500, 16, 'Ready');

		this._labelSize = new Label(super.stage, 500, 2, 'Size: hz');

		var progressBar:ProgressBar = new ProgressBar();

		this._progressBar = progressBar;

		var button:PushButton = new PushButton(super.stage, 310, 40, 'Add to list', this.handler_pressButton);
		button.enabled = false;

		button = new PushButton(super.stage, 590, 40, 'Save as..', this.handler_saveButton);

		this._inputText = new InputText(super.stage, 10, 42, 'or type custom URL here...');
		this._inputText.addEventListener(FocusEvent.FOCUS_IN, 
			function(event:Event):void {
				var inp:InputText = InputText(event.currentTarget); 
				inp.removeEventListener(event.type, arguments.callee);
				inp.text = '';
				button.enabled = true;
			}
		);

		this._inputText.width = 290;


		var comboBox:ComboBox = new ComboBox(super.stage, 10, 10, 'choose ULR', uris);

		this._comboBox = comboBox;

		comboBox.width = 400;
		comboBox.addEventListener(Event.SELECT, this.handler_select);

		for (var i:uint = 0; i < uris.length; i++) {
			comboBox.addItem( {label:uris[i]} );
			this._comboBoxIndex++;
		}

		this._qname = new QName('ru.goodcore', 'GIFMovieClip');

		this.handler_resize(null);
	}

	//-------------------------------------------------------------------------
	//
	//   Events handlers
	//
	//-------------------------------------------------------------------------

	/**
	 * @private
	 */
	private function handler_select(event:Event = null):void {
		
		if (this._comboBox.selectedItem == null)
			return;

		if (this._mc && this._mc.parent)
			this._mc.parent.removeChild(this._mc);
		
		this._mc = null;
		
		System.gc();

		this._label.text = 'Loading...';

		this._comboBox.removeEventListener(Event.SELECT, this.handler_select);
		
		super.stage.addChild(this._progressBar);

		var uri:String = ComboBox(event.target).selectedItem.label;

		var request:URLRequest = new URLRequest(uri);
	//	var request:URLRequest = new URLRequest('http://69.16.188.134:80/v8u2m5i8/cds/tags/4-1003896.js?dopvhost=adserving.cpxadroit.com&doppl=0b0dcc51472fdb6b477fdb3b026f6316d3aa6864&dopsig=2a67b80ca6fac54f77ea76e291528fd5');

/*
		var urlLoader:URLLoader = new URLLoader();
		urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
		urlLoader.addEventListener(Event.COMPLETE,			this.handler_complete);
		urlLoader.addEventListener(ProgressEvent.PROGRESS,	this.handler_progress);
		urlLoader.addEventListener(IOErrorEvent.IO_ERROR,	this.handler_error);
		urlLoader.load(request);
*/

		var loader:Loader = new Loader();
		var li:LoaderInfo = loader.contentLoaderInfo;

		li.addEventListener(Event.COMPLETE,			this.handler_swfComplete);
		li.addEventListener(ProgressEvent.PROGRESS,	this.handler_swfProgress);
		li.addEventListener(IOErrorEvent.IO_ERROR,	this.handler_swfError);
		
		var context:LoaderContext
		//context = new LoaderContext(false, null, SecurityDomain.currentDomain);
		loader.load(request, context);
	}

	/**
	 * @private
	 */
	private function handler_delayChange(event:Event):void {
		var checkBox:CheckBox = CheckBox(event.target);
		this._useDelays = checkBox.selected;
		if (this._comboBox.selectedItem) {
			this._comboBox.dispatchEvent( new Event(Event.SELECT) );
		}
	}

	/**
	 * @private
	 */
	private function handler_saveButton(event:Event):void {
		var fr:FileReference = new FileReference();
		fr.save(this._data, 'image.swf');
		//fr.browse();
	}

	/**
	 * @private
	 */
	private function handler_pressButton(event:Event):void {
		this._comboBox.removeEventListener(Event.SELECT, this.handler_select);

		if (this._inputText.text == '')
			return;

		var comboBox:	ComboBox = this._comboBox;

		for (var i:uint = 0; i < this._comboBoxIndex; i++) {
			comboBox.selectedIndex = i;
			if (comboBox.selectedItem.label == this._inputText.text)
				return;
		}

		var item:		Object = {label: this._inputText.text};
		comboBox.addItem( item );

		this._comboBoxIndex++;
		comboBox.selectedItem = item;
		comboBox.selectedIndex = this._comboBoxIndex - 1;
		
		this._comboBox.addEventListener(Event.SELECT, this.handler_select);
		this._comboBox.dispatchEvent( new Event(Event.SELECT) );
	}

	/**
	 * @private
	 */
	private function handler_progress(event:Event):void {
		var urlLoader:URLLoader = URLLoader(event.target);

		this._label.text = 'Loaded ' + urlLoader.bytesLoaded + ' bytes';

		this._labelSize.text = 'Size: ' + urlLoader.bytesTotal + ' bytes';

		this._progressBar.maximum = urlLoader.bytesTotal;
		this._progressBar.value = urlLoader.bytesLoaded;
	}

	/**
	 * @private
	 */
	private function handler_swfError(event:Event):void {
		trace('handler_swfError');
		var li:LoaderInfo = event.target as LoaderInfo;
/*
		var bytes:ByteArray = new ByteArray();
		li.bytes.readInt();
		
		//bytes.writeBytes(li.bytes, 0, 152);
		//li.bytes.writeBytes(li.bytes, 0, 152);
		//li.bytes.length = 152;
		trace(li.bytes.length);
		trace(traceByteArray(li.bytes));
*/
	}
	/**
	 * @private
	 */
	private function handler_swfProgress(event:ProgressEvent):void {
		trace('handler_swfProgress')
		//trace(SecurityDomain.currentDomain == SecurityDomain.currentDomain); // true
	}

	/**
	 * @private
	 */
	private function handler_swfComplete(event:Event):void {
		trace('handler_swfComplete')
		//trace(SecurityDomain.currentDomain == SecurityDomain.currentDomain); // true
		//trace(ApplicationDomain.currentDomain == ApplicationDomain.currentDomain); // false
		var li:LoaderInfo = event.target as LoaderInfo;
		li.removeEventListener(Event.COMPLETE,			this.handler_swfComplete);

		var loader:Loader = li.loader;
		//getDefinitionNames(li.bytes);

		//trace(li.content);

		li.addEventListener(Event.COMPLETE,			this.handler_bytesComplete);
		loader.loadBytes(li.bytes);
		//this._addedChild = super.addChild(li.content);
		
		this._data = li.bytes;
		
		//System.gc();
		
		//loader.unload();

		//loader.load( new URLRequest(this._comboBox.selectedItem.label) );

		//var content:* = loader.content;
		
	}
private var _addedChild:DisplayObject;
	/**
	 * @private
	 */
	private function handler_bytesComplete(event:Event):void {
		var li:LoaderInfo = event.target as LoaderInfo;
		li.removeEventListener(Event.COMPLETE,			this.handler_bytesComplete);
		var loader:Loader = li.loader;
		//super.addChild(li.content).y = 200;

		if (this._addedChild)
			super.removeChild(this._addedChild);

		this._addedChild = null;

		System.gc();
		//return;

		//super.stage.addChild(li.content);

		//getDefinitionNames(li.bytes);
		//trace(li.content);

		var source:		DisplayObject = li.content as DisplayObject;
		var bitmapData:	BitmapData = new BitmapData(source.width, source.height, true, 0x00000000);
		var bitmap:		Bitmap = new Bitmap(bitmapData);
	
		super.addChild(bitmap);
		bitmapData.draw(source);
		//bitmap.x = (super.stage.stageWidth - bitmap.width) >> 1;
		bitmap.y = (super.stage.stageHeight - bitmap.height) >> 1;
		//super.addChild(bitmap);
	}

	/**
	 * @private
	 */
	private function handler_complete(event:Event):void {
		var urlLoader:URLLoader = URLLoader(event.target);
		urlLoader.removeEventListener(Event.COMPLETE,			this.handler_complete);
		urlLoader.removeEventListener(ProgressEvent.PROGRESS,	this.handler_progress);
		urlLoader.removeEventListener(IOErrorEvent.IO_ERROR,	this.handler_error);

		super.stage.removeChild(this._progressBar);
		
		return;
		
		//var o:Object = ObjectUtil.copy(urlLoader);

		this._start = getTimer();
		
		//this._qname = new QName('ru.goodcore', 'GIFMovieClip_$' + int(Math.random() * 1e5).toString(16));

		// 
		var swf:SWFGIFMovieClip = new SWFGIFMovieClip(urlLoader.data, this._qname, true, this._useDelays ? super.stage.frameRate : 0);
		
		var appDomain:	ApplicationDomain;

		//appDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
		//appDomain = new ApplicationDomain(super.stage.loaderInfo.applicationDomain);
		//appDomain = new ApplicationDomain(super.loaderInfo.applicationDomain);
		//appDomain = new ApplicationDomain();
		//trace(ApplicationDomain.currentDomain == ApplicationDomain.currentDomain);
		//trace(super.loaderInfo.applicationDomain == super.stage.loaderInfo.applicationDomain);
		//appDomain = super.stage.loaderInfo.applicationDomain;
		//appDomain = super.loaderInfo.applicationDomain;
		appDomain = ApplicationDomain.currentDomain;
		//trace(super.loaderInfo.applicationDomain.parentDomain);
		//trace(super.loaderInfo.applicationDomain.parentDomain);
		//trace(ApplicationDomain.currentDomain.parentDomain);
		//trace(super.loaderInfo.applicationDomain.parentDomain == super.stage.loaderInfo.applicationDomain.parentDomain);
		//trace(super.loaderInfo.applicationDomain == new ApplicationDomain());
		//trace(new ApplicationDomain(super.loaderInfo.applicationDomain).parentDomain);
		//appDomain = null;

		//trace(Error.throwError(IllegalOperationError, 2012));

		//Trace.setListener(this.handler_trace);
		//Trace.setLevel(Trace.METHODS_AND_LINES_WITH_ARGS);
		//Trace.setLevel(Trace.METHODS_AND_LINES_WITH_ARGS, Trace.FILE);

		var loader:Loader = new Loader();

		var loaderInfo:LoaderInfo = loader.contentLoaderInfo;

		//var appDomain:	ApplicationDomain = loaderInfo.applicationDomain;

		var context:	LoaderContext = new LoaderContext(false,  appDomain);

		loaderInfo.addEventListener(Event.COMPLETE, this.handler_resourceComplete);
		loader.loadBytes( swf, context );
	}

	/**
	 * @private
	 */
	private function handler_error(event:Event):void {
		var urlLoader:URLLoader = URLLoader(event.target);
		urlLoader.removeEventListener(Event.COMPLETE,			this.handler_complete);
		urlLoader.removeEventListener(ProgressEvent.PROGRESS,	this.handler_progress);
		urlLoader.removeEventListener(IOErrorEvent.IO_ERROR,	this.handler_error);

		this._label.text = 'Error loading';

		super.stage.removeChild(this._progressBar);

		this._comboBox.removeItem(this._comboBox.selectedItem);
		//this._comboBox.selectedIndex = -1;
		this._comboBox.selectedItem = null;
		this._comboBoxIndex--;

		this._comboBox.addEventListener(Event.SELECT, this.handler_select);
		this._comboBox.dispatchEvent( new Event(Event.SELECT) );
	}

	/**
	 * @private
	 */
	private function handler_resourceComplete(event:Event):void {
		var loaderInfo:LoaderInfo = LoaderInfo(event.target);
		loaderInfo.removeEventListener(Event.COMPLETE, this.handler_resourceComplete);

		var hash:String;

		//var startTime:uint = getTimer();
		//hash = by.blooddy.crypto.MD5.hashBytes(loaderInfo.bytes);
		//trace( 'done at ', getTimer() - startTime, hash );

		//startTime = getTimer();
		//hash = ru.goodcore.utils.crypto.MD5.hashBytes(loaderInfo.bytes);
		//trace( 'done at ', getTimer() - startTime, hash );
		//return;
		//Trace.setLevel(Trace.OFF);
		//Trace.setListener(null);
		
		var c:Class;

		//var c:Class = loaderInfo.applicationDomain.getDefinition( this._qname.toString() ) as Class;
		
		//c = getDefinitionByName( 'flash.utils::IExternalizable' ) as Class;
		//trace('class:', c);
		
		//var a:* = new c();
		
		c = getDefinitionByName( this._qname.toString() ) as Class;
		//c = getDefinitionByName( 'flash.display::MovieClip' ) as Class;
		var mc:	MovieClip = new c();
		mc.cacheAsBitmap = true;

		//mc.scrollRect = new Rectangle(0, 0, 600, 600);
		super.addChild(mc);
		this._mc = mc;
		
		
	/*
		var bitmapData:BitmapData = new BitmapData(3, 1, true);
		bitmapData.setPixel32(0, 0, 0x14FF0000);
		bitmapData.setPixel32(1, 0, 0x1400FF00);
		bitmapData.setPixel32(2, 0, 0x140000FF);
	*/
	/*
		var bitmapData:BitmapData = new BitmapData(3, 3, true, 0x00000000);
		bitmapData.setPixel32(0, 0, 0x14000000);
		bitmapData.setPixel32(1, 0, 0x14000000);
		bitmapData.setPixel32(0, 1, 0x14000000);
		bitmapData.setPixel32(1, 1, 0x14000000);
	*/
	/*
		var bitmapData:BitmapData = new BitmapData(2, 2, true, 0x00000000);
		bitmapData.setPixel32(0, 0, 0x14000000);

		
		//this._bitmapData = bitmapData;
		
		var tv:Shape = new Shape();
		var g:Graphics = tv.graphics;
		g.beginBitmapFill(bitmapData);
		g.drawRect(0, 0, mc.width, mc.height);
		g.endFill();
		
		mc.addChild(tv);
	*/
		this._label.text = 'Done at ' + (getTimer() - this._start) + ' ms';

		this._comboBox.addEventListener(Event.SELECT, this.handler_select);
		
		this.handler_resize(null);
/*
		super.addEventListener(
			Event.ENTER_FRAME, 
			function(event:Event):void {
				event.target.removeEventListener(event.type, arguments.callee);
				handler_resize(null);
			}
		);
*/
	}

	/**
	 * @private
	 */
	private function handler_resize(event:Event):void {
		var displObj:	DisplayObject = this._progressBar;

		if (displObj) {
			displObj.x = (super.stage.stageWidth - displObj.width) >> 1;
			displObj.y = (super.stage.stageHeight - displObj.height) >> 1;
		}

		displObj = this._mc;

		if (displObj) {
			//trace(displObj.width);
			displObj.x = (super.stage.stageWidth - displObj.width) >> 1;
			displObj.y = (super.stage.stageHeight - displObj.height) >> 1;
		}

	}

	/**
	 * @private
	 */
	private function handler_trace(... args):void {
		trace(args, '\n');
		trace('');
	}




}
}